package pathways;

/**
 * Title:        Pathways
 * Description:  Pure Java version of the Pathways Project.
 * Copyright:    Copyright (c) 2002
 * Company:      Ants Technologies
 * @author Veejay Sani
 * @version 1.0
 */

import java.util.Vector;

public class CConnectionPoint
{
  public CConnectionPoint()
  {
    branches = new Vector();
    reactionsLeadingToMe = new Vector();
    lastAttachedBranch = attachedBranch = NOBRANCHATTACHED;
  }

  public void attachBranch(int branchNum)
  {
    if (attachedBranch != branchNum)
    {
      // hide existing
      if (isAnyBranchAttached())
        setVisibilityForBranch(attachedBranch,false,null);

      // show requested
      setVisibilityForBranch(branchNum,true,null);
      attachedBranch = branchNum;
    }
  }

  public void attachBranch2(int branchNum)
  {
    // only difference from attachBranch is that
    // it does not check if the attachedBranch != branchNum
    // this is needed for loading pathways
    // what happens is that when loading a pathway
    // first all the reactions are loaded and then 
    // substratesAsEnzymes and then the branches visibility
    // When loading reactions one branch becomes attached
    // This also implicitly sets the visibility of the reactions
    // After this a SubstrateAsEnzyme is added
    // Imagine if SubAsEnz was added to a branch that
    // was invisible already (when loading reactions)
    // Now branch visibility routine runs and tries to make sure
    // that correct branches are attached So the situtation 
    // described above should be fixed and the SubsAsEnz should 
    // disappear since it is part of a hidden branch
    // but this does not happen because when the branch-visibility
    // routine sets the attached branches the correct branch is 
    // already attached (from loading reactions) and if the attachBranch
    // routine checks for attachedBranch != branchNum then
    // the attaching of the branch is not reinforced
    // and the subAsEnz remains visible.
    // Thus the need for this routine  
  
  
    //if (attachedBranch != branchNum)
    //{
      // hide existing
      if (isAnyBranchAttached())
        setVisibilityForBranch(attachedBranch,false,null);

      // show requested
      setVisibilityForBranch(branchNum,true,null);
      attachedBranch = branchNum;
    //}
  }
  
  public void detachAll(CConnectionPoint toPoint)
  {
    if (isAnyBranchAttached())
    {
      lastAttachedBranch = attachedBranch;
      setVisibilityForBranch(attachedBranch,false,toPoint);
      attachedBranch = NOBRANCHATTACHED;
    }
  }

  public void detachAll2()
  {
    for (int i = 0 ; i < this.branches.size(); i++)
    {
      CReaction rxn = (CReaction)branches.get(i);
      setVisibilityForBranch(rxn,false,null);
      attachedBranch = NOBRANCHATTACHED;
    }
  }
  
  public void rawDetachAll()
  {
    if (this.isAnyBranchAttached())
    {
      lastAttachedBranch = attachedBranch;
      attachedBranch = NOBRANCHATTACHED;
    }
  }
  
  public boolean isAnyBranchAttached()
  {
    //System.out.println(attachedBranch);
    return (attachedBranch >= 0);
  }
  
  public int getBranchNumForHeadReaction(CReaction rxn)
  {
    int branchNum = -1;
    
    for (int i = 0; i < branches.size(); i++)
    {
      if (rxn == (CReaction)branches.get(i))
      {
        branchNum = i; 
      }  
    }
    
    return branchNum;
  }
  
  private void setVisibilityForBranch(int branchNum, boolean visibility, CConnectionPoint toPoint)
  {
    CReaction rxn;

    rxn = (CReaction)branches.get(branchNum);

    setVisibilityForBranch(rxn,visibility, toPoint);
  }

  private void setVisibilityForBranch(CReaction headRxn, boolean visibility, CConnectionPoint toPoint)
  {
    Vector rxns;
    CSubstrate prod = headRxn.getProduct();
    CConnectionPoint p = null;
    
    headRxn.setVisibility(visibility);
    
    // stop if the point is in the substrate
    if (!isPointInSubstrate(toPoint,prod))
    {
      for (int i=0; i < 4; i++)
      {
        p = prod.getConnectionPoint(i);
        
        if (visibility)
        {
          p.makeLastAttachedBranchVisible(); 
        }
        else
        {
          p.detachAll(toPoint);
        }
      }
    }
  }

  /*
  private void setVisibilityForBranch(CReaction headRxn, boolean visibility)
  {
    Vector rxns;
    CSubstrate prod = headRxn.getProduct();
    CConnectionPoint p = null;
    
    headRxn.setVisibility(visibility);
    
    for (int i=0; i < 4; i++)
    {
      p = prod.getConnectionPoint(i);
      
      if (visibility)
      {
        p.makeLastAttachedBranchVisible(); 
      }
      else
      {
        p.detachAll();
      }
    }
  }
  */
  private boolean isPointInSubstrate(CConnectionPoint p, CSubstrate sub)
  {
    if (sub.getConnectionPoint0() == p)
       return true;
    else if (sub.getConnectionPoint1() == p)
       return true;
    else if (sub.getConnectionPoint2() == p)
       return true;
    else if (sub.getConnectionPoint3() == p)
       return true;
    else
       return false;
  }
  
  public int getAttachedBranch()
  {
    return attachedBranch;
  }

  public Vector getFirstReactionAtEachBranch()
  {
    return branches;
  }
  
  public Vector getReactionsLeadingToMe()
  {
    return reactionsLeadingToMe;
  }
  
  public void makeLastAttachedBranchVisible()
  {
    // attaches last branch
    // if no branch currently attached
    // and a valid last branch exists
    
    if (!isAnyBranchAttached())
    {
      if (lastAttachedBranch != NOBRANCHATTACHED)
      {
         setVisibilityForBranch(lastAttachedBranch,true,null);
         attachedBranch = lastAttachedBranch;
      } 
    }
  }
  
  public void rawSetAttachedBranch(int branch)
  {
    attachedBranch = branch;
  }

  public void rawSetAttachedBranch(CReaction rxn)
  {
    int branchNum = getBranchNumForHeadReaction(rxn);
    
    if (branchNum >= 0)
       rawSetAttachedBranch(branchNum);
  }
  
  public CReaction getAttachedReaction()
  {
    if (attachedBranch != NOBRANCHATTACHED)
      return  (CReaction)branches.get(attachedBranch);
    else
      return null;
  }
   
  private Vector branches;
  private int attachedBranch;
  private Vector reactionsLeadingToMe;
  public final int NOBRANCHATTACHED = -1;
  private int lastAttachedBranch;
}